﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Terraria.Localization;

namespace Terraria.Net.Sockets
{
	// Token: 0x0200015A RID: 346
	public class TcpSocket : ISocket
	{
		// Token: 0x17000119 RID: 281
		// (get) Token: 0x06000EC8 RID: 3784 RVA: 0x0000E17B File Offset: 0x0000C37B
		public int MessagesInQueue
		{
			get
			{
				return this._messagesInQueue;
			}
		}

		// Token: 0x06000EC9 RID: 3785 RVA: 0x0000E183 File Offset: 0x0000C383
		public TcpSocket()
		{
			this._connection = new TcpClient();
			this._connection.NoDelay = true;
		}

		// Token: 0x06000ECA RID: 3786 RVA: 0x00400090 File Offset: 0x003FE290
		public TcpSocket(TcpClient tcpClient)
		{
			this._connection = tcpClient;
			this._connection.NoDelay = true;
			IPEndPoint ipendPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint;
			this._remoteAddress = new TcpAddress(ipendPoint.Address, ipendPoint.Port);
		}

		// Token: 0x06000ECB RID: 3787 RVA: 0x0000E1BD File Offset: 0x0000C3BD
		void ISocket.Close()
		{
			this._remoteAddress = null;
			this._connection.Close();
		}

		// Token: 0x06000ECC RID: 3788 RVA: 0x0000E1D1 File Offset: 0x0000C3D1
		bool ISocket.IsConnected()
		{
			return this._connection != null && this._connection.Client != null && this._connection.Connected;
		}

		// Token: 0x06000ECD RID: 3789 RVA: 0x004000FC File Offset: 0x003FE2FC
		void ISocket.Connect(RemoteAddress address)
		{
			TcpAddress tcpAddress = (TcpAddress)address;
			this._connection.Connect(tcpAddress.Address, tcpAddress.Port);
			this._remoteAddress = address;
		}

		// Token: 0x06000ECE RID: 3790 RVA: 0x00400130 File Offset: 0x003FE330
		private void ReadCallback(IAsyncResult result)
		{
			Tuple<SocketReceiveCallback, object> tuple = (Tuple<SocketReceiveCallback, object>)result.AsyncState;
			tuple.Item1(tuple.Item2, this._connection.GetStream().EndRead(result));
		}

		// Token: 0x06000ECF RID: 3791 RVA: 0x0040016C File Offset: 0x003FE36C
		private void SendCallback(IAsyncResult result)
		{
			Tuple<SocketSendCallback, object> tuple = (Tuple<SocketSendCallback, object>)result.AsyncState;
			try
			{
				this._connection.GetStream().EndWrite(result);
				tuple.Item1(tuple.Item2);
			}
			catch (Exception)
			{
				((ISocket)this).Close();
			}
		}

		// Token: 0x06000ED0 RID: 3792 RVA: 0x00006B58 File Offset: 0x00004D58
		void ISocket.SendQueuedPackets()
		{
		}

		// Token: 0x06000ED1 RID: 3793 RVA: 0x0000E1F5 File Offset: 0x0000C3F5
		void ISocket.AsyncSend(byte[] data, int offset, int size, SocketSendCallback callback, object state)
		{
			this._connection.GetStream().BeginWrite(data, 0, size, new AsyncCallback(this.SendCallback), new Tuple<SocketSendCallback, object>(callback, state));
		}

		// Token: 0x06000ED2 RID: 3794 RVA: 0x0000E220 File Offset: 0x0000C420
		void ISocket.AsyncReceive(byte[] data, int offset, int size, SocketReceiveCallback callback, object state)
		{
			this._connection.GetStream().BeginRead(data, offset, size, new AsyncCallback(this.ReadCallback), new Tuple<SocketReceiveCallback, object>(callback, state));
		}

		// Token: 0x06000ED3 RID: 3795 RVA: 0x0000E24B File Offset: 0x0000C44B
		bool ISocket.IsDataAvailable()
		{
			return this._connection.GetStream().DataAvailable;
		}

		// Token: 0x06000ED4 RID: 3796 RVA: 0x0000E25D File Offset: 0x0000C45D
		RemoteAddress ISocket.GetRemoteAddress()
		{
			return this._remoteAddress;
		}

		// Token: 0x06000ED5 RID: 3797 RVA: 0x004001C4 File Offset: 0x003FE3C4
		bool ISocket.StartListening(SocketConnectionAccepted callback)
		{
			IPAddress any = IPAddress.Any;
			string ipString;
			if (Program.LaunchParameters.TryGetValue("-ip", out ipString) && !IPAddress.TryParse(ipString, out any))
			{
				any = IPAddress.Any;
			}
			this._isListening = true;
			this._listenerCallback = callback;
			if (this._listener == null)
			{
				this._listener = new TcpListener(any, Netplay.ListenPort);
			}
			try
			{
				this._listener.Start();
			}
			catch (Exception)
			{
				return false;
			}
			ThreadPool.QueueUserWorkItem(new WaitCallback(this.ListenLoop));
			return true;
		}

		// Token: 0x06000ED6 RID: 3798 RVA: 0x0000E265 File Offset: 0x0000C465
		void ISocket.StopListening()
		{
			this._isListening = false;
		}

		// Token: 0x06000ED7 RID: 3799 RVA: 0x0040025C File Offset: 0x003FE45C
		private void ListenLoop(object unused)
		{
			while (this._isListening && !Netplay.disconnect)
			{
				try
				{
					ISocket socket = new TcpSocket(this._listener.AcceptTcpClient());
					Console.WriteLine(Language.GetTextValue("Net.ClientConnecting", socket.GetRemoteAddress()));
					this._listenerCallback(socket);
				}
				catch (Exception)
				{
				}
			}
			this._listener.Stop();
		}

		// Token: 0x04001257 RID: 4695
		private byte[] _packetBuffer = new byte[1024];

		// Token: 0x04001258 RID: 4696
		private int _packetBufferLength;

		// Token: 0x04001259 RID: 4697
		private List<object> _callbackBuffer = new List<object>();

		// Token: 0x0400125A RID: 4698
		private int _messagesInQueue;

		// Token: 0x0400125B RID: 4699
		private TcpClient _connection;

		// Token: 0x0400125C RID: 4700
		private TcpListener _listener;

		// Token: 0x0400125D RID: 4701
		private SocketConnectionAccepted _listenerCallback;

		// Token: 0x0400125E RID: 4702
		private RemoteAddress _remoteAddress;

		// Token: 0x0400125F RID: 4703
		private bool _isListening;
	}
}
